package com.rr.jvm.demo;

import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * @author RR
 * @date 2021/12/8 23:27
 */
/*
 * 软引用测试，内存不足时会首先回收这部分内存，如果内存还不足报oom异常
 * 测试参数：-Xmx20m -XX:+PrintGCDetails -verbose:gc
 * */
public class Demo2SoftReferenceTest {

    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) throws IOException {
//        test1();
//        test2();
        test3();
    }

    //使用普通强引用，会内存溢出
    static void test1() throws IOException {
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new byte[_4MB]);
        }
        System.in.read();
    }
    //使用软引用，内存不足时会回收软引用中的对象
    static void test2(){
        List<SoftReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
            System.out.println(ref.get());
            list.add(ref);
        }
        System.out.println("循环结束，list.size:" + list.size());
        for (SoftReference<byte[]> softReference : list) {
            System.out.println(softReference.get());
        }
    }

    //软引用配合引用队列使用，与test2相比，增加引用队列，记录可以删除的软引用对象
    static void test3(){
        List<SoftReference<byte[]>> list = new ArrayList<>();
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();
        for (int i = 0; i < 5; i++) {
            //创建软引用对象时可以指定引用队列
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }
        Reference<? extends byte[]> poll = queue.poll();
        while (poll != null) {
            list.remove(poll);
            poll = queue.poll();
            System.out.println("删除软引用对象");
        }
        System.out.println("============");
        System.out.println("list.size="+list.size());
        for (SoftReference<byte[]> softReference : list) {
            System.out.println(softReference.get());
        }
    }
}
